package TangramCore;

import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Arrays;

public class HladinaEdit extends Hladina {
    Dilek.Validity dv[];
    Obrys.Validity ov;
    Rectangle2D rect = new Rectangle2D.Double(),tmp = new Rectangle2D.Double();
    //private Point2D.Double pt = new Point2D.Double ();
    int vzhled;
    
    private boolean cleared = true, hidden = false, difAdd;
    
    Vzhled vzhledObrys;
    Vzhled vzhledDilky[] = {null, null};
    Paint paintBack;// = new Color(0, 128, 0);//Color.white;//new Color(0, 128, 0);
    
    public HladinaEdit(Dilek d[], Obrys o, Vzhled vd, Vzhled vdsel, Vzhled vo, Paint bp, Rectangle rp) {
        relpos = rp;
        //this.skladacka = d[0].skladacka;
        //this.d = d;
        //this.o = o;
        this.dv = Dilek.Validity.getAll(d);
        //Arrays.sort(dv);
        this.ov = new Obrys.Validity(o);
        vzhledObrys = vo;
        vzhledDilky[0] = vd;
        vzhledDilky[1] = vdsel;
        difAdd = vzhledObrys.add != Math.max(vzhledDilky[0].add,vzhledDilky[0].add);
        paintBack = bp;
    }
    
  /*public HladinaEdit(Rectangle r, Dilek d[], Obrys o, Vzhled vd, Vzhled vdsel, Vzhled vo) {
    this(d, o, vd, vdsel, vo);
    resize(r);
  }*/
    public void update(Dilek d[], Obrys o){
        //tmp.setRect(0,0,0,0);
        if (vzhled == VZHLED_OBRYS)
            addRect2D(rect, ov.getLastValid());
        else
            for (int i = 0; i < dv.length; i++)
                addRect2D(rect, dv[i].getLastValid());
        ov = new Obrys.Validity(o);
        dv = Dilek.Validity.getAll(d);
    }
    
    @Override
    public void resize(){
        double add = vzhled == VZHLED_OBRYS ? vzhledObrys.add : Math.max(vzhledDilky[0].add,vzhledDilky[1].add);
        double mer = (double)Math.min(pos.width,pos.height) / (Skladacka.MAXCOORD + 2*add);
        at =  AffineTransform.getTranslateInstance(pos.x + ( pos.width - mer*Skladacka.MAXCOORD)/2,pos.y + (pos.height - mer*Skladacka.MAXCOORD)/2);
        at.scale(mer,mer);
    }
    
    @Override
    public void resize(Rectangle r){
        super.resize(r);
        cleared = true;
        resize();
    }
    
    @Override
    public void show() { //jen priznak, rect se nastavi az pri prvnim validate
        if(!hidden)
            return;
        cleared = true;
        hidden = false;
    }
    
    @Override
    public void validate() {
        if (hidden)
            return;
        //System.out.println(cleared);
        if (vzhled == VZHLED_OBRYS) {
            ov.validate(cleared, tmp);
            addRect2D(rect, tmp);
        } else {
            boolean zOrderChanged = false;
            for (int i = 0; i < dv.length; i++) {
                if(dv[i].validate(cleared, tmp)>Dilek.INV_VALID)
                    zOrderChanged = true;
                addRect2D(rect, tmp);
            }
            if(zOrderChanged){
                Arrays.sort(dv);
                //System.out.println("sorting Edit");
            }
        }
        addTransformedRect2D(obr.rectUpdate,rect);
        //addRect(rectUpdate, at.createTransformedShape(rect).getBounds()); //transform
        cleared = false;
        rect.setRect(0, 0, 0, 0);
    }
    
    @Override
    public void hide() {
        if (hidden)
            return;
        hidden = true;
        rect.setRect(0,0,0,0);
        if(paintBack == null){
            if (vzhled == VZHLED_OBRYS)
                addRect2D(rect, ov.getLastValid());
            else
                for (int i = 0; i < dv.length; i++)
                    addRect2D(rect, dv[i].getLastValid());
            addTransformedRect2D(obr.rectUpdate,rect);
        }
        else
            addRect2D(obr.rectUpdate,pos);
//    addRect(rectUpdate, at.createTransformedShape(rect).getBounds()); //transform
    }
    
    @Override
    public void draw(Graphics2D g) {
        if(hidden)
            return;
        AffineTransform old=g.getTransform();
        g.transform(at);
        if (vzhled == VZHLED_OBRYS)
            vzhledObrys.plotShape(g, ov.o);
        else
            for (int i = 0; i < dv.length; i++)
                vzhledDilky[dv[i].d.jeVybran() ? 1 : 0].plotShape(g, dv[i].d);
        g.setTransform(old);
    }
    
    public int prepniVzhled(int v) {
        if(v != vzhled)
            prepniVzhled();
        return vzhled;
    }
    
    public int prepniVzhled() {
        hide();
        if(vzhled == VZHLED_DILKY)
            vzhled = VZHLED_OBRYS;
        else
            vzhled = VZHLED_DILKY;
        if(difAdd)
            resize();
        show();
        return vzhled;
    }
    public int getVzhled(){
        return vzhled;
    }
    
    public void suspend() {
        if (vzhled == VZHLED_DILKY)
            return;
        hide();
        if(vzhled == VZHLED_OBRYS)
            vzhled = VZHLED_OBRYS_SUSPENDED;
        else
            vzhled = VZHLED_OBRYS;
        //resize ??? asi neni hezke poskoceni obrazce v dusledku rozdilneho v.add
        show();
    }
    
    @Override
    public void clear(Graphics2D g) {
        if(paintBack != null){
            g.setPaint(paintBack);
            g.fill(pos);
        }
    }
    public Dilek getDilekFromPoint(Point2D p) {
        //p je v normalizovanych souradnicich
        int i = dv.length - 1;
        for (; i >= 0; i--)
            if (dv[i].d.contains(p))
                break;
        return i == -1 ? null : dv[i].d;
    }
    public Obrys getObrysFromPoint(Point2D p){
        //p je v normalizovanych souradnicich
        return ov.o.contains(p) ? ov.o : null;
    }
    public void setVzhled(Vzhled vd, Vzhled vdsel, Vzhled vo){
        hide();
        vzhledObrys = vo;
        vzhledDilky[0] = vd;
        vzhledDilky[1] = vdsel;
        resize();
        show();
    }
    @Override
    public boolean contains(Point p){
        return false;
    }

}
